package com.inter.controller.payment;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.inter.entity.interentity.pay.wxapp.request.RequestWeiXinAppPay;
import com.inter.entity.interentity.pay.wxapp.request.RequestWeiXinAppPayData;
import com.inter.entity.interentity.pay.wxapp.request.RequestWeiXinAppPayTradeData;
import com.inter.entity.interentity.pay.wxapp.response.ResponseWeiXinAppPay;
import com.inter.entity.interentity.pay.wxapp.response.ResponseWeiXinAppPayData;
import com.inter.entity.interentity.pay.wxapp.response.ResponseWeiXinAppPayTradeData;
import com.inter.entity.interentity.pay.wxscan.request.RequestWeiXinScanPay;
import com.inter.entity.interentity.pay.wxscan.request.RequestWeiXinScanPayData;
import com.inter.entity.interentity.pay.wxscan.request.RequestWeiXinScanPayTradeData;
import com.inter.entity.interentity.pay.wxscan.response.ResponseWeiXinScanPay;
import com.inter.entity.interentity.pay.wxscan.response.ResponseWeiXinScanPayData;
import com.inter.entity.interentity.pay.wxscan.response.ResponseWeiXinScanPayTradeData;
import com.inter.entity.interentity.utils.UtilsInterfacesPackage;
import com.inter.service.SequenceService;
import com.inter.utils.MD5;
import com.inter.utils.pay.WxPayUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Controller
@Api(description = "微信扫二维码支付")
public class WeiXinPayScanController {

    private static Logger logger = Logger.getLogger(WeiXinPayScanController.class);
    @Autowired
    private SequenceService sequenceService;

    /***微信扫二维码支付付款接口 ：之前tcl的项目在使用
     *
     * @param requestWeiXinScanPay
     * @param request
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/wxScanPay", produces = "application/json;charset=utf-8", method = RequestMethod.POST)
    @CrossOrigin
    @ResponseBody
    @ApiOperation(value = "微信扫码支付下单", response = ResponseWeiXinScanPay.class)
    public String wxPayScan(@ApiParam @RequestBody RequestWeiXinScanPay requestWeiXinScanPay, HttpServletRequest request) throws Exception {
        // 1，生成流水号
        String connSeqNo = sequenceService.getPackageTaskNo();
        // 2,生成当前时间戳
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String curtime = df.format(new Date());
        //3，定义回报报文
        String jsonString;
        UtilsInterfacesPackage utils = new UtilsInterfacesPackage();
        String requestStr = JSON.toJSONString(requestWeiXinScanPay);
        if (requestStr == null) {
            System.out.println("请求报文不合法:requestStr为空");
            jsonString = utils.dataWeiKong(connSeqNo, curtime);
            return jsonString;
        } else {
            System.out.println("前端请求报文是：" + requestStr);
            RequestWeiXinScanPay requestPackage = JSONArray.parseObject(requestStr, RequestWeiXinScanPay.class);
            String requestSign = requestPackage.getSign();
            if (requestSign == null) {
                System.out.println("请求报文不合法:sign为空");
                jsonString = utils.dataWeiKong(connSeqNo, curtime);
                return jsonString;
            } else {
                System.out.println("请求的签名是：" + requestSign);
                RequestWeiXinScanPayData requestData = requestPackage.getData();
                if (requestData == null) {
                    System.out.println("请求报文不合法:data为空");
                    jsonString = utils.dataWeiKong(connSeqNo, curtime);
                    return jsonString;
                } else {
                    String partnerCode = requestData.getPartnerCode();
                    String ConnSeqNo = requestData.getConnSeqNo();
                    String tradeTime = requestData.getTradeTime();
                    String token = requestData.getToken();
                    String tradeType = requestData.getTradeType();
                    String lang = requestData.getLang();
                    RequestWeiXinScanPayTradeData requestTradeData = requestData.getTradeData();
                    if (requestTradeData == null || partnerCode == null || ConnSeqNo == null || tradeTime == null || token == null || tradeType == null || lang == null) {
                        System.out.println("请求报文不合法:data参数不合法");
                        jsonString = utils.dataWeiKong(connSeqNo, curtime);
                        return jsonString;
                    } else {
                        String orderId = requestTradeData.getOrderId();
                        String amount = requestTradeData.getAmount();
                        String body = requestTradeData.getBody();
                        if (orderId == null || orderId == "" || amount == null || amount == "" || body == null || body == "") {
                            System.out.println("请求报文不合法:orderId,amount,APPID或者body不可以为空！");
                            jsonString = utils.dataWeiKong(connSeqNo, curtime);
                            return jsonString;
                        } else {
                            // 将请求体json转成String
                            String str = JSON.toJSONString(requestData);
                            // 将Str拿去计算签名
                            String sign = utils.calculateSignature(str);
                            System.out.println("计算的签名是：" + sign);
                            if (!requestSign.equalsIgnoreCase(sign)) {
                                System.out.println("签名验证失败！");
                                jsonString = utils.publicMessage(ConnSeqNo, partnerCode, tradeTime, token, tradeType);
                                return jsonString;
                            } else {
                                // 统一下单，返回xml，用return_code判断统一下单结果,获取prepay_id等预支付成功信息
                                // 获取ip地址:
                                String ipAddrStr = WxPayUtil.getIp2(request);
                                System.out.println("新的获取的ip地址是：" + ipAddrStr);
                                // 将传过来的金额处理一下
                                boolean flag = WxPayUtil.isInteger(amount);
                                // 如果是整型
                                if (flag == true) {
                                    int Amount = Integer.valueOf(amount).intValue();
                                    int totel_fee = Amount * 100;
                                    String prePayInfoXml = WxPayUtil.UnifiedOrderScan(body, orderId, totel_fee, ipAddrStr);
                                    logger.info("Controller中的prePayInfoXml：" + prePayInfoXml);
                                    // 生成包含prepay_id的map，map传入前端
                                    Map<String, Object> map = new HashMap<String, Object>();
                                    map = WxPayUtil.getPayScanMap(prePayInfoXml);
                                    logger.info("Controller中的map：" + map);

                                    String prepay_id = (String) map.get("prepay_id");
                                    String trade_type = (String) map.get("trade_type");
                                    String code_url = (String) map.get("code_url");
                                    String return_msg = (String) map.get("return_msg");
                                    String return_code = (String) map.get("return_code");
                                    String result_code = (String) map.get("result_code");
                                    if ((prepay_id != null || trade_type != null || trade_type != "" || prepay_id != "" || code_url != null || code_url != "") && return_code.equalsIgnoreCase("success") && result_code.equalsIgnoreCase("success") && return_msg.equalsIgnoreCase("OK")) {
                                        //回报报文TradeData
                                        ResponseWeiXinScanPayTradeData responseTradeData = new ResponseWeiXinScanPayTradeData();
                                        responseTradeData.setPrepay_id(prepay_id);
                                        responseTradeData.setTrade_type(trade_type);
                                        responseTradeData.setCode_url(code_url);
                                        responseTradeData.setOrderId(orderId);
                                        //回报Data
                                        ResponseWeiXinScanPayData data = new ResponseWeiXinScanPayData();
                                        data.setConnSeqNo(ConnSeqNo);
                                        data.setPartnerCode(partnerCode);
                                        data.setToken(token);
                                        data.setTradeType(tradeType);
                                        data.setTradeTime(tradeTime);
                                        data.setTradeRstCode(1000);
                                        data.setTradeRstMessage("success");
                                        data.setTradeData(responseTradeData);

                                        ResponseWeiXinScanPay responseWeiXinPay = new ResponseWeiXinScanPay();
                                        responseWeiXinPay.setData(data);
                                        responseWeiXinPay.setSign(MD5.calcMD5(JSON.toJSONString(data)));
                                        // 返回给调用者的报文
                                        jsonString = JSON.toJSONString(responseWeiXinPay);
                                        System.out.println("响应报文：" + jsonString);
                                        return jsonString;
                                    } else {
                                        //如果没有取到微信的预下单号，就返回错误
                                        //回报Data
                                        ResponseWeiXinScanPayData data = new ResponseWeiXinScanPayData();
                                        data.setConnSeqNo(ConnSeqNo);
                                        data.setPartnerCode(partnerCode);
                                        data.setToken(token);
                                        data.setTradeType(tradeType);
                                        data.setTradeTime(tradeTime);
                                        data.setTradeRstCode(1200);
                                        data.setTradeRstMessage("微信错误：" + return_msg);

                                        ResponseWeiXinScanPay responseWeiXinPay = new ResponseWeiXinScanPay();
                                        responseWeiXinPay.setData(data);
                                        responseWeiXinPay.setSign(MD5.calcMD5(JSON.toJSONString(data)));
                                        // 返回给调用者的报文
                                        jsonString = JSON.toJSONString(responseWeiXinPay);
                                        System.out.println("响应报文：" + jsonString);
                                        return jsonString;
                                    }
                                } else {
                                    // DecimalFormat("#")表示float类型格式化时不要小数点了
                                    DecimalFormat decimalFormat = new DecimalFormat("#");
                                    float Amount = Float.parseFloat(amount);
                                    int totel_fee = Integer.parseInt(decimalFormat.format(Amount * 100));
                                    String prePayInfoXml = WxPayUtil.UnifiedOrderScan(body, orderId, totel_fee, ipAddrStr);
                                    logger.info("Controller中的prePayInfoXml：" + prePayInfoXml);
                                    // 生成包含prepay_id的map，map传入前端
                                    Map<String, Object> map = new HashMap<String, Object>();
                                    map = WxPayUtil.getPayScanMap(prePayInfoXml);
                                    logger.info("Controller中的map：" + map);
                                    // 将订单号放入map，用以支付后处理
                                    String prepay_id = (String) map.get("prepay_id");
                                    String trade_type = (String) map.get("trade_type");
                                    String code_url = (String) map.get("code_url");

                                    String return_msg = (String) map.get("return_msg");
                                    String return_code = (String) map.get("return_code");
                                    String result_code = (String) map.get("result_code");

                                    if ((prepay_id != null || trade_type != null || trade_type != "" || prepay_id != "" || code_url != null || code_url != "") && return_code.equalsIgnoreCase("success") && result_code.equalsIgnoreCase("success") && return_msg.equalsIgnoreCase("OK")) {
                                        //回报报文TradeData
                                        ResponseWeiXinScanPayTradeData responseTradeData = new ResponseWeiXinScanPayTradeData();
                                        responseTradeData.setPrepay_id(prepay_id);
                                        responseTradeData.setTrade_type(trade_type);
                                        responseTradeData.setCode_url(code_url);
                                        responseTradeData.setOrderId(orderId);
                                        //回报Data
                                        ResponseWeiXinScanPayData data = new ResponseWeiXinScanPayData();
                                        data.setConnSeqNo(ConnSeqNo);
                                        data.setPartnerCode(partnerCode);
                                        data.setToken(token);
                                        data.setTradeType(tradeType);
                                        data.setTradeTime(tradeTime);
                                        data.setTradeRstCode(1000);
                                        data.setTradeRstMessage("success");
                                        data.setTradeData(responseTradeData);

                                        ResponseWeiXinScanPay responseWeiXinPay = new ResponseWeiXinScanPay();
                                        responseWeiXinPay.setData(data);
                                        responseWeiXinPay.setSign(MD5.calcMD5(JSON.toJSONString(data)));
                                        // 返回给调用者的报文
                                        jsonString = JSON.toJSONString(responseWeiXinPay);
                                        System.out.println("响应报文：" + jsonString);
                                        return jsonString;
                                    } else {
                                        //如果没有取到微信的预下单号，就返回错误
                                        //回报Data
                                        ResponseWeiXinScanPayData data = new ResponseWeiXinScanPayData();
                                        data.setConnSeqNo(ConnSeqNo);
                                        data.setPartnerCode(partnerCode);
                                        data.setToken(token);
                                        data.setTradeType(tradeType);
                                        data.setTradeTime(tradeTime);
                                        data.setTradeRstCode(1200);
                                        data.setTradeRstMessage("微信错误：" + return_msg);

                                        ResponseWeiXinScanPay responseWeiXinPay = new ResponseWeiXinScanPay();
                                        responseWeiXinPay.setData(data);
                                        responseWeiXinPay.setSign(MD5.calcMD5(JSON.toJSONString(data)));
                                        // 返回给调用者的报文
                                        jsonString = JSON.toJSONString(responseWeiXinPay);
                                        System.out.println("响应报文：" + jsonString);
                                        return jsonString;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * @2016年12月14日下午3:47:29
     * @function：动态生成二维码图片，并直接以流的形式输出到页面
     * @author ：lj
     */
    public void getQRCode(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String code_url = request.getParameter("code_url");
        MultiFormatWriter multi = new MultiFormatWriter();
        Map map = new HashMap();
        map.put(EncodeHintType.CHARACTER_SET, "UTF-8");//设置字符集编码类型
        BitMatrix bitMatrix = null;
        try {
            bitMatrix = multi.encode(code_url, BarcodeFormat.QR_CODE, 300, 300, map);
            BufferedImage image = toBufferedImage(bitMatrix);
            //输出二维码图片流
            try {
                ImageIO.write(image, "png", response.getOutputStream());
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } catch (WriterException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public BufferedImage toBufferedImage(BitMatrix matrix) {
        int WHITE = 0xFFFFFFFF;
        int BLACK = 0xFF000000;
        int width = matrix.getWidth();
        int height = matrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);
            }
        }
        return image;
    }

}

